package controllers

import (
	"beego/comm/cipher"
	"beego/comm/db"
	"beego/comm/entity"
	"beego/models"
	"encoding/json"
	"fmt"
	"math/rand"
	"time"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
)

type LoginController struct {
	beego.Controller
}

func getRandomString(l int) string {
	str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	bytes := []byte(str)
	result := []byte{}
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := 0; i < l; i++ {
		result = append(result, bytes[r.Intn(len(bytes))])
	}
	return string(result)
}

func checkError(err error) {
	if nil != err {
		panic(err)
	}
}

func (c *LoginController) GetPubKey() {
	defer func() {
		err := recover()
		if nil != err {
			c.Data["json"] = map[string]interface{}{
				"pubKey":    "",
				"errorInfo": err,
			}
			c.ServeJSON()
		}
	}()
	var user models.User
	json.Unmarshal(c.Ctx.Input.RequestBody, &user)
	user_name := user.UserName
	o := orm.NewOrm()
	var maps []orm.Params
	o.Raw(`select user_public_key from user_info where user_name = ? `).SetArgs(user_name).Values(&maps)
	if len(maps) == 0 {
		panic(fmt.Sprintf("[GetPubKey]用户名[%v]不存在", user_name))
	} else if len(maps) > 1 {
		panic(fmt.Sprintf("[GetPubKey]用户名[%v]有多个", user_name))
	}
	c.Data["json"] = map[string]interface{}{
		"pubKey":    cipher.GetKey(maps[0]["user_public_key"].(string)),
		"errorInfo": "",
	}
	c.ServeJSON()
}

func (c *LoginController) Login() {
	defer func() {
		err := recover()
		if nil != err {
			c.Data["json"] = map[string]interface{}{
				"userName":    "",
				"loginStatus": false,
				"loginID":     "",
				"errorInfo":   err,
			}
			c.ServeJSON()
		}
	}()
	var user models.User
	json.Unmarshal(c.Ctx.Input.RequestBody, &user)
	user_name := user.UserName
	user_pwd := user.Password
	var loginStatus bool
	var loginID string
	o := orm.NewOrm()
	var maps []orm.Params
	o.Raw(`select user_pwd, user_private_key from user_info where user_name = ?`).SetArgs(user_name).Values(&maps)
	if 1 == len(maps) {
		user_private_key := maps[0]["user_private_key"].(string)
		input_pwd := cipher.RSA_Decrypt(user_pwd, user_private_key)
		store_pwd := cipher.RSA_Decrypt(maps[0]["user_pwd"].(string), user_private_key)
		if input_pwd != store_pwd {
			panic("密码错误!")
		}
		loginID = getRandomString(49)
		_, err := db.RedisSet("login-"+user_name, loginID)
		if nil == err {
			loginStatus = true
		} else {
			panic(fmt.Sprintf("%s", err))
		}
	} else if 0 == len(maps) {
		panic(fmt.Sprintf("[Login]用户名[%v]不存在", user_name))
	} else {
		panic(fmt.Sprintf("[Login]用户名[%v]有多个", user_name))
	}
	c.Data["json"] = map[string]interface{}{
		"userName":    user_name,
		"loginStatus": loginStatus,
		"loginID":     loginID,
		"errorInfo":   "",
	}
	c.ServeJSON()
}

func (c *LoginController) Logout() {
	var user entity.User2
	json.Unmarshal(c.Ctx.Input.RequestBody, &user)
	user_name := user.UserName
	user_loginID := user.LoginID
	var loginStatus bool
	var errorInfo, loginID string
	value, err := db.RedisGet("login-" + user_name)
	if nil == err && value == user_loginID {
		_, err2 := db.RedisDel("login-" + user.UserName)
		user_name = ""
		loginStatus = false
		loginID = ""
		if nil != err2 {
			errorInfo = "redis: 注销异常"
		}
	} else {
		errorInfo = "注销失败"
	}
	c.Data["json"] = map[string]interface{}{
		"userName":    user_name,
		"loginStatus": loginStatus,
		"loginID":     loginID,
		"errorInfo":   errorInfo,
	}
	c.ServeJSON()
}
